package entities;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.lang.reflect.Method;
import java.util.Map;
import java.io.ObjectOutputStream;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.FileInputStream;
import java.io.File;

public class EntityManager {

	private static Map<String, List> AllInstance = new HashMap<String, List>();
	
	private static List<User> UserInstances = new LinkedList<User>();
	private static List<Student> StudentInstances = new LinkedList<Student>();
	private static List<Teacher> TeacherInstances = new LinkedList<Teacher>();
	private static List<Manager> ManagerInstances = new LinkedList<Manager>();
	private static List<Team> TeamInstances = new LinkedList<Team>();
	private static List<Group> GroupInstances = new LinkedList<Group>();
	private static List<Daily> DailyInstances = new LinkedList<Daily>();
	private static List<Plan> PlanInstances = new LinkedList<Plan>();
	private static List<Apply> ApplyInstances = new LinkedList<Apply>();
	private static List<StudentInTeam> StudentInTeamInstances = new LinkedList<StudentInTeam>();
	private static List<StudentInGroup> StudentInGroupInstances = new LinkedList<StudentInGroup>();

	
	/* Put instances list into Map */
	static {
		AllInstance.put("User", UserInstances);
		AllInstance.put("Student", StudentInstances);
		AllInstance.put("Teacher", TeacherInstances);
		AllInstance.put("Manager", ManagerInstances);
		AllInstance.put("Team", TeamInstances);
		AllInstance.put("Group", GroupInstances);
		AllInstance.put("Daily", DailyInstances);
		AllInstance.put("Plan", PlanInstances);
		AllInstance.put("Apply", ApplyInstances);
		AllInstance.put("StudentInTeam", StudentInTeamInstances);
		AllInstance.put("StudentInGroup", StudentInGroupInstances);
	} 
		
	/* Save State */
	public static void save(File file) {
		
		try {
			
			ObjectOutputStream stateSave = new ObjectOutputStream(new FileOutputStream(file));
			
			stateSave.writeObject(UserInstances);
			stateSave.writeObject(StudentInstances);
			stateSave.writeObject(TeacherInstances);
			stateSave.writeObject(ManagerInstances);
			stateSave.writeObject(TeamInstances);
			stateSave.writeObject(GroupInstances);
			stateSave.writeObject(DailyInstances);
			stateSave.writeObject(PlanInstances);
			stateSave.writeObject(ApplyInstances);
			stateSave.writeObject(StudentInTeamInstances);
			stateSave.writeObject(StudentInGroupInstances);
			
			stateSave.close();
					
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	/* Load State */
	public static void load(File file) {
		
		try {
			
			ObjectInputStream stateLoad = new ObjectInputStream(new FileInputStream(file));
			
			try {
				
				UserInstances =  (List<User>) stateLoad.readObject();
				AllInstance.put("User", UserInstances);
				StudentInstances =  (List<Student>) stateLoad.readObject();
				AllInstance.put("Student", StudentInstances);
				TeacherInstances =  (List<Teacher>) stateLoad.readObject();
				AllInstance.put("Teacher", TeacherInstances);
				ManagerInstances =  (List<Manager>) stateLoad.readObject();
				AllInstance.put("Manager", ManagerInstances);
				TeamInstances =  (List<Team>) stateLoad.readObject();
				AllInstance.put("Team", TeamInstances);
				GroupInstances =  (List<Group>) stateLoad.readObject();
				AllInstance.put("Group", GroupInstances);
				DailyInstances =  (List<Daily>) stateLoad.readObject();
				AllInstance.put("Daily", DailyInstances);
				PlanInstances =  (List<Plan>) stateLoad.readObject();
				AllInstance.put("Plan", PlanInstances);
				ApplyInstances =  (List<Apply>) stateLoad.readObject();
				AllInstance.put("Apply", ApplyInstances);
				StudentInTeamInstances =  (List<StudentInTeam>) stateLoad.readObject();
				AllInstance.put("StudentInTeam", StudentInTeamInstances);
				StudentInGroupInstances =  (List<StudentInGroup>) stateLoad.readObject();
				AllInstance.put("StudentInGroup", StudentInGroupInstances);
				
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
		
	/* create object */  
	public static Object createObject(String Classifer) {
		try
		{
			Class c = Class.forName("entities.EntityManager");
			Method createObjectMethod = c.getDeclaredMethod("create" + Classifer + "Object");
			return createObjectMethod.invoke(c);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}
	
	/* add object */  
	public static Object addObject(String Classifer, Object ob) {
		try
		{
			Class c = Class.forName("entities.EntityManager");
			Method addObjectMethod = c.getDeclaredMethod("add" + Classifer + "Object", Class.forName("entities." + Classifer));
			return  (boolean) addObjectMethod.invoke(c, ob);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}	
	
	/* add objects */  
	public static Object addObjects(String Classifer, List obs) {
		try
		{
			Class c = Class.forName("entities.EntityManager");
			Method addObjectsMethod = c.getDeclaredMethod("add" + Classifer + "Objects", Class.forName("java.util.List"));
			return  (boolean) addObjectsMethod.invoke(c, obs);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}
	
	/* Release object */
	public static boolean deleteObject(String Classifer, Object ob) {
		try
		{
			Class c = Class.forName("entities.EntityManager");
			Method deleteObjectMethod = c.getDeclaredMethod("delete" + Classifer + "Object", Class.forName("entities." + Classifer));
			return  (boolean) deleteObjectMethod.invoke(c, ob);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return false;
		}
	}
	
	/* Release objects */
	public static boolean deleteObjects(String Classifer, List obs) {
		try
		{
			Class c = Class.forName("entities.EntityManager");
			Method deleteObjectMethod = c.getDeclaredMethod("delete" + Classifer + "Objects", Class.forName("java.util.List"));
			return  (boolean) deleteObjectMethod.invoke(c, obs);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return false;
		}
	}		 	
	
	 /* Get all objects belongs to same class */
	public static List getAllInstancesOf(String ClassName) {
			 return AllInstance.get(ClassName);
	}	

   /* Sub-create object */
	public static User createUserObject() {
		User o = new User();
		return o;
	}
	
	public static boolean addUserObject(User o) {
		return UserInstances.add(o);
	}
	
	public static boolean addUserObjects(List<User> os) {
		return UserInstances.addAll(os);
	}
	
	public static boolean deleteUserObject(User o) {
		return UserInstances.remove(o);
	}
	
	public static boolean deleteUserObjects(List<User> os) {
		return UserInstances.removeAll(os);
	}
	public static Student createStudentObject() {
		Student o = new Student();
		return o;
	}
	
	public static boolean addStudentObject(Student o) {
		return StudentInstances.add(o);
	}
	
	public static boolean addStudentObjects(List<Student> os) {
		return StudentInstances.addAll(os);
	}
	
	public static boolean deleteStudentObject(Student o) {
		return StudentInstances.remove(o);
	}
	
	public static boolean deleteStudentObjects(List<Student> os) {
		return StudentInstances.removeAll(os);
	}
	public static Teacher createTeacherObject() {
		Teacher o = new Teacher();
		return o;
	}
	
	public static boolean addTeacherObject(Teacher o) {
		return TeacherInstances.add(o);
	}
	
	public static boolean addTeacherObjects(List<Teacher> os) {
		return TeacherInstances.addAll(os);
	}
	
	public static boolean deleteTeacherObject(Teacher o) {
		return TeacherInstances.remove(o);
	}
	
	public static boolean deleteTeacherObjects(List<Teacher> os) {
		return TeacherInstances.removeAll(os);
	}
	public static Manager createManagerObject() {
		Manager o = new Manager();
		return o;
	}
	
	public static boolean addManagerObject(Manager o) {
		return ManagerInstances.add(o);
	}
	
	public static boolean addManagerObjects(List<Manager> os) {
		return ManagerInstances.addAll(os);
	}
	
	public static boolean deleteManagerObject(Manager o) {
		return ManagerInstances.remove(o);
	}
	
	public static boolean deleteManagerObjects(List<Manager> os) {
		return ManagerInstances.removeAll(os);
	}
	public static Team createTeamObject() {
		Team o = new Team();
		return o;
	}
	
	public static boolean addTeamObject(Team o) {
		return TeamInstances.add(o);
	}
	
	public static boolean addTeamObjects(List<Team> os) {
		return TeamInstances.addAll(os);
	}
	
	public static boolean deleteTeamObject(Team o) {
		return TeamInstances.remove(o);
	}
	
	public static boolean deleteTeamObjects(List<Team> os) {
		return TeamInstances.removeAll(os);
	}
	public static Group createGroupObject() {
		Group o = new Group();
		return o;
	}
	
	public static boolean addGroupObject(Group o) {
		return GroupInstances.add(o);
	}
	
	public static boolean addGroupObjects(List<Group> os) {
		return GroupInstances.addAll(os);
	}
	
	public static boolean deleteGroupObject(Group o) {
		return GroupInstances.remove(o);
	}
	
	public static boolean deleteGroupObjects(List<Group> os) {
		return GroupInstances.removeAll(os);
	}
	public static Daily createDailyObject() {
		Daily o = new Daily();
		return o;
	}
	
	public static boolean addDailyObject(Daily o) {
		return DailyInstances.add(o);
	}
	
	public static boolean addDailyObjects(List<Daily> os) {
		return DailyInstances.addAll(os);
	}
	
	public static boolean deleteDailyObject(Daily o) {
		return DailyInstances.remove(o);
	}
	
	public static boolean deleteDailyObjects(List<Daily> os) {
		return DailyInstances.removeAll(os);
	}
	public static Plan createPlanObject() {
		Plan o = new Plan();
		return o;
	}
	
	public static boolean addPlanObject(Plan o) {
		return PlanInstances.add(o);
	}
	
	public static boolean addPlanObjects(List<Plan> os) {
		return PlanInstances.addAll(os);
	}
	
	public static boolean deletePlanObject(Plan o) {
		return PlanInstances.remove(o);
	}
	
	public static boolean deletePlanObjects(List<Plan> os) {
		return PlanInstances.removeAll(os);
	}
	public static Apply createApplyObject() {
		Apply o = new Apply();
		return o;
	}
	
	public static boolean addApplyObject(Apply o) {
		return ApplyInstances.add(o);
	}
	
	public static boolean addApplyObjects(List<Apply> os) {
		return ApplyInstances.addAll(os);
	}
	
	public static boolean deleteApplyObject(Apply o) {
		return ApplyInstances.remove(o);
	}
	
	public static boolean deleteApplyObjects(List<Apply> os) {
		return ApplyInstances.removeAll(os);
	}
	public static StudentInTeam createStudentInTeamObject() {
		StudentInTeam o = new StudentInTeam();
		return o;
	}
	
	public static boolean addStudentInTeamObject(StudentInTeam o) {
		return StudentInTeamInstances.add(o);
	}
	
	public static boolean addStudentInTeamObjects(List<StudentInTeam> os) {
		return StudentInTeamInstances.addAll(os);
	}
	
	public static boolean deleteStudentInTeamObject(StudentInTeam o) {
		return StudentInTeamInstances.remove(o);
	}
	
	public static boolean deleteStudentInTeamObjects(List<StudentInTeam> os) {
		return StudentInTeamInstances.removeAll(os);
	}
	public static StudentInGroup createStudentInGroupObject() {
		StudentInGroup o = new StudentInGroup();
		return o;
	}
	
	public static boolean addStudentInGroupObject(StudentInGroup o) {
		return StudentInGroupInstances.add(o);
	}
	
	public static boolean addStudentInGroupObjects(List<StudentInGroup> os) {
		return StudentInGroupInstances.addAll(os);
	}
	
	public static boolean deleteStudentInGroupObject(StudentInGroup o) {
		return StudentInGroupInstances.remove(o);
	}
	
	public static boolean deleteStudentInGroupObjects(List<StudentInGroup> os) {
		return StudentInGroupInstances.removeAll(os);
	}
  
}

